﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;

namespace DotNetExtensions.AspNet.Helpers
{
    public static class DataTableMapper
    {
        public static List<T> ToList<T>(this DataTable data) where T : new()
        {
            List<T> t = data.Mapper<T>(null, true);
            return t;
        }

        public static List<T> ToList<T>(this DataTable data, string prefix, bool ignoreCase = true) where T : new()
        {
            List<T> t = data.Mapper<T>(prefix, ignoreCase);
            return t;
        }


        private static List<T> Mapper<T>(this DataTable data, string prefix, bool ignoreCase = true) where T : new()
        {
            List<T> t = new List<T>();
            int columnscount = data.Columns.Count;
            var properties = new T().GetType().GetProperties();
            var rowscount = data.Rows.Count;
            for (int i = 0; i < rowscount; i++)
            {
                var model = new T();
                foreach (var p in properties)
                {
                    var keyName = prefix + p.Name + "";
                    if (ignoreCase)
                        keyName = keyName.ToUpper();
                    for (int j = 0; j < columnscount; j++)
                    {
                        if (data.Columns[j].ColumnName.ToUpper() == keyName && data.Rows[i][j] != null)
                        {
                            string pval = data.Rows[i][j].ToString();
                            if (!string.IsNullOrEmpty(pval))
                            {
                                try
                                {
                                    if (p.PropertyType.IsGenericType && p.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
                                    {
                                        p.SetValue(model, Convert.ChangeType(data.Rows[i][j], p.PropertyType.GetGenericArguments()[0]), null);
                                    }
                                    else
                                    {
                                        p.SetValue(model, Convert.ChangeType(data.Rows[i][j], p.PropertyType), null);
                                    }
                                }
                                catch (Exception x)
                                {
                                    throw x;
                                }
                            }
                            break;
                        }
                    }
                }
                t.Add(model);
            }


            return t;
        }
    }
}
